Libraries I may use called


library(tidyverse)
# install for visualizations 
library(ggplot2)
# install to combine date and time
library(lubridate)
# for melting a df
library(reshape)
library(data.table)

Perceived Health Status

Reading in the first dataset, perceived health status.

perceived_health_status <- read_csv("../data/perceived_health_status.csv")
# dnmk <- read_csv("../data/denmark_only_phs.csv")
# perceived_health_status_once <- read_csv("../data/perceived_health_status_once.csv")

Inspecting the denmark only data:

# dnmk %>% 
#   filter(Sex == "Total")

It appears that then

Inspecting the perceived health data:

perceived_health_status %>% 
  filter(`Reference area` == "Denmark")

Inspect original perceived health data:

# perceived_health_status_once%>% 
#   filter(`Reference area` == "Denmark")
perceived_health_status

Filtering.


perceived_health_status_stripped <- perceived_health_status %>% 
  filter(TIME_PERIOD == 2022) %>% 
  filter(REF_AREA == "AUT") %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "15 years or over")  

perceived_health_status_stripped
NA

As it appears that after 2007, the number of observations are more significant in number, I will limit my data to 2007 and later. But, since it appears the number of observations drops off in 2024, I will limit my data to a range of 2007-2023. As well, I want to capture all genders and ages. (Corrected “==” to be “%in%” and that corrected much the problem I was running into.)


# input code to limit year range, age range, and gender in perceived health status data

phs <- perceived_health_status %>% 
  filter(TIME_PERIOD %in% c(2007:2023)) %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "15 years or over")

phs
NA

It turns out that Denmark’s data comes only from a population of 15-24 year old, which would be excluded when I filter for age range collective/Total. (Corrected “==” to be “%in%” which corrected what I was seeing.)


# perceived_health_status_once %>% 
#   filter(TIME_PERIOD %in% c(2007:2023)) %>% 
#   filter(Sex == "Total") %>% 
#   filter(AGE == "Y_GE15") 

# sort(unique(perceived_health_status_once$Age))
# 
# perceived_health_status_once %>% 
#   group_by(AGE) %>%
#   summarize(n=n())

Inspect the data for the number of years it covers.


barplot(table(perceived_health_status$TIME_PERIOD), main = "number of observations of year in the data")

NA
NA

Inspect the data for the number of age categories it covers.

barplot(table(perceived_health_status$Age), main = "number of observations of age groups in the data")

Inspecting the data for balance in the health status column.


phs %>% 
  group_by(HEALTH_STATUS) %>% 
  summarize(n=n())
NA

Which countries are most heavily represented in the data? Denmark was selected to be included I will download a Denmark only data and investigate why it is no longer located in this data.


phs %>% 
  group_by(`Reference area`) %>%
  summarize(n=n())
NA
phs %>% 
  group_by(AGE) %>%
  summarize(n=n())
NA

The final state of my Perceived Health Status data will be:


phs
NA

Education Levels

Reading in the second dataset, education levels.


# education_level <- read_csv("../data/educational_attainment_distribution_age_gender.csv")
# education_levels_defined <- read_csv("../data/educational_attainment_distribution.csv")
education_levels_three <- read_csv("../data/educational_attainment.csv")

Early data exploration in the education data

el_third <- education_levels_three %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "From 25 to 64 years") %>% 
  filter(TIME_PERIOD == 2010) %>% 
  filter(OBS_STATUS == "A") %>% 
  filter(REF_AREA == "AUT") %>% 
  filter(STATISTICAL_OPERATION == "OBS")

el_third

# ISCED11A_5T8 = Tertiary education
# ISCED11A_3_4 = Upper secondary or post-secondary non-tertiary education
# ISCED11A_0T2 = Below upper secondary education
education_levels_three
NA

Verify that there are simply three categories for the education level attained and Education attainment level columns


sort(unique(education_levels_three$ATTAINMENT_LEV))
[1] "ISCED11A_0T2" "ISCED11A_3_4" "ISCED11A_5T8"
sort(unique(education_levels_three$`Educational attainment level`))
[1] "Below upper secondary education"                         
[2] "Tertiary education"                                      
[3] "Upper secondary or post-secondary non-tertiary education"
sort(unique(education_levels_three$STATISTICAL_OPERATION))
[1] "OBS" "SE" 

I want to use the observed values and not the standard error values at this time.


education_levels_three %>% 
  filter(STATISTICAL_OPERATION == "OBS")
NA

I want to see the representation of countries in the data. Certain countries are significantly under represented.

barplot(table(education_levels_three$`Reference area`), main = "number of observations of countries in the data")

barplot(table(education_levels_three$TIME_PERIOD), main = "number of observations of year in the data")

check to see which years are present in the data. Base on the lack of data in the years prior to about 1998, I will limit the dataset to 1998-2024.


sort(unique(education_levels_three$TIME_PERIOD))
 [1] 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994
[15] 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
[29] 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
[43] 2023 2024
education_levels_three_time <- education_levels_three %>% 
  filter(TIME_PERIOD %in% c(1998:2024))

I would like to discover which of the countries are under represented.

education_levels_three_time %>% 
  group_by(`Reference area`) %>%
  summarize(n=n())

I want to drop any countries whose count is less than 1800.


# count the frequency of each country
country_count <- table(education_levels_three_time$`Reference area`)

# I do not want any fewer rows for a country than this
num_in_data <- 1800

# which countries match or exceed that number
countries_to_keep <- names(country_count[country_count > num_in_data])

# filter the dataset to keep only rows of countries who are 
#represented in the data a certain number of times or more
education_levels_three_time_countries <- education_levels_three_time[education_levels_three_time$`Reference area` %in% countries_to_keep, ]

education_levels_three_time_countries 
NA
NA

Check out which ages are available to filter by.

sort(unique(education_levels_three_time_countries$Age))
[1] "From 25 to 34 years" "From 25 to 64 years" "From 35 to 44 years"
[4] "From 45 to 54 years" "From 55 to 64 years"

Check number of times each age range is represented in the data


barplot(table(education_levels_three_time_countries$Age), main = "number of observations of age in the data")

NA
NA

Filter using all of the methods left that I want to filter by: all genders, ages, as well as only observed data, not the standard error.


el <- education_levels_three_time_countries %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "From 25 to 64 years") %>% 
  filter(OBS_STATUS == "A") %>%
  filter(STATISTICAL_OPERATION == "OBS")
el

The final state of my education level data will be:


# selected all adults from age, and all genders, and only observed values no standard error values
el[1:2,]
NA

Social and Community connection pulled from the Wellbeing dataset

Reading in the third dataset, social connectedness from the wellbeing dataset.


social_wellbeing <- read_csv("../data/social_connection_wellbeing.csv")

View the data.

social_wellbeing[1:2, ]

Inspect the UNIT_MEASURE column’s unique values.


sort(unique(social_wellbeing$UNIT_MEASURE))
[1] "0_TO_10"           "H_WK"              "PT_POP_Y_GE15"    
[4] "PT_POP_Y_GE15_SUB" "PT_POP_Y_GE16"     "PT_POP_Y_GE16_SUB"

sort(unique(social_wellbeing$Measure))
[1] "Feeling lonely"                                            
[2] "Lack of social support"                                    
[3] "Life satisfaction"                                         
[4] "Life satisfaction score less than 5"                       
[5] "Satisfaction with personal relationships"                  
[6] "Satisfaction with personal relationships score less than 5"
[7] "Social support"                                            
[8] "Time spent in social interactions"                         

social_wellbeing %>% 
  filter(TIME_PERIOD == 2022) %>% 
  filter(REF_AREA == "AUS") %>% 
  filter(Measure %in% c("Social support", "Lack of social support")) %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "Total") %>% 
  filter(`Education level` == "Total")
NA

Assigning filtered dataset to new variable.


social_support_or_lack <- social_wellbeing %>% 
  filter(TIME_PERIOD %in% c(2007:2023)) %>% 
  filter(Measure %in% c("Social support", "Lack of social support")) %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "Total") %>% 
  filter(`Education level` == "Total")

social_support_or_lack[1:2, ]
NA

barplot(table(social_support_or_lack$TIME_PERIOD), main = "frequency of years in the data")


# find unique values for Measure column
sort(unique(social_wellbeing$Measure))
[1] "Feeling lonely"                                            
[2] "Lack of social support"                                    
[3] "Life satisfaction"                                         
[4] "Life satisfaction score less than 5"                       
[5] "Satisfaction with personal relationships"                  
[6] "Satisfaction with personal relationships score less than 5"
[7] "Social support"                                            
[8] "Time spent in social interactions"                         

How is satisfaction with personal relationships scored?

social_wellbeing %>% 
  filter(Measure == "Satisfaction with personal relationships score less than 5")

Inspect which Measures are listed with the 0 to 10 unit measure.


social_wellbeing_0_10 <- social_wellbeing %>% 
  filter(UNIT_MEASURE == "0_TO_10")

social_wellbeing_0_10[1:2, ]
NA

sort(unique(social_wellbeing_0_10$Measure))
[1] "Life satisfaction"                       
[2] "Satisfaction with personal relationships"

Limit the data to totals on sex, age, and education, in order to capture a population not a specific group within a population. As well, narrow down the date range and select only the Measures whose unit measure is 0-10.


satisfaction_life_rels <- social_wellbeing %>% 
  filter(TIME_PERIOD %in% c(2007:2023)) %>% 
  filter(Measure %in% c("Life satisfaction", "Satisfaction with personal relationships")) %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "Total") %>% 
  filter(`Education level` == "Total")
  
satisfaction_life_rels[1:2, ]
NA

barplot(table(satisfaction_life_rels$TIME_PERIOD))

Looking into the feeling lonely measure.



lonely <- social_wellbeing %>% 
  filter(TIME_PERIOD %in% c(2007:2023)) %>%   
  filter(Measure == "Feeling lonely") %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "Total") %>% 
  filter(`Education level` == "Total")
  
lonely[1:2, ]
NA
barplot(table(lonely$TIME_PERIOD), main = "how often certain years are rep'd in data")


num_countries_repd_in_lonely <- lonely %>% 
  group_by(`Reference area`) %>% 
  summarise(n=n())


ctrs_desc <- order(num_countries_repd_in_lonely$n, decreasing = TRUE)

num_countries_repd_in_lonely[ctrs_desc,][1:2, ]
NA
NA
barplot(table(social_support_or_lack$TIME_PERIOD), main = "how often each year shows up in dataset" )


social_interactions <- social_wellbeing %>% 
  filter(TIME_PERIOD %in% c(2007:2023)) %>%   
  filter(Measure == "Time spent in social interactions") %>% 
  filter(Sex == "Total") %>% 
  filter(Age == "Total") %>% 
  filter(`Education level` == "Total")

social_interactions[1:2, ]
NA
barplot(table(social_interactions$TIME_PERIOD))


social_interactions %>% 
  group_by(`Reference area`) %>% 
  summarise(n=n())
NA

The final datasets from wellbeing data I have chosen are as follows:


# measured as a percentage fo the adult population and is well represented across all years in selected data 
social_support_or_lack[1:2, ]

# measured as a percentage of the adult population, and is almost exclusively 2018 and 2022
lonely[1:2, ]

# years most represented in the data: 2013, 2018, 2022; it is measured on a 0-10 scale. 
satisfaction_life_rels[1:2, ]

# measured in units of hours per week, across various years, very difficult to compare, I will exclude this data for now
social_interactions[1:2, ]
NA

Safety

Reading in the second dataset, education levels.


safety_regions <- read_csv("../data/safety_regions.csv")
safety <- safety_regions %>% 
  filter(TIME_PERIOD %in% c(2007:2023)) %>% 
  filter(TERRITORIAL_LEVEL == "CTRY") %>% 
  filter(Sex %in% c("Total", "Not applicable")) %>% 
  filter(`Observation status` == "Normal value")

safety[1:2, ]
NA

barplot(table(safety$OBS_VALUE), main = "frequency of percentage of pop measured unsafe instances in the data")

sort(unique(safety$`Observation status`))
[1] "Normal value"

The final dataset from safety data I have chosen are as follows:

safety[1:2,]

Final datasets are:


# perceived health status, subjective survey of good, fair, and bad health
phs[1:2, ]

# selected all adults from age, and all genders, and only observed values no standard error values
el[1:2, ]

# measured as a percentage fo the adult population and is well represented across all years in selected data 
social_support_or_lack[1:2, ]

# measured as a percentage of the adult population, and is almost exclusively 2018 and 2022
lonely[1:2, ]

# years most represented in the data: 2013, 2018, 2022; it is measured on a 0-10 scale. 
satisfaction_life_rels[1:2, ]

# measured in cases per 100,000 persons, well distributed across selected years
safety[1:2,]
NA

###Merging data sets together into one

Order the data’s country column (REF_AREA) alphabetically.


# Order the data's country column (`Reference area`) alphabetically.

phs_v1 <- phs[order(phs$`Reference area`),] 

el_v1 <- el[order(el$`Reference area`),]

safety_v1 <- safety[order(safety$`Reference area`),]

social_support_or_lack_v1 <- social_support_or_lack[order(social_support_or_lack$`Reference area`),]

lonely_v1 <- lonely[order(lonely$`Reference area`),]

satisfaction_life_rels_v1 <- satisfaction_life_rels[order(satisfaction_life_rels$`Reference area`),]
 


phs_v1 # percentage of the population
el_v1 # percentage of the population
safety_v1 # measured in cases per 100,000 persons
social_support_or_lack_v1 # percentage of the population
lonely_v1 # percentage of the population
satisfaction_life_rels_v1[1:2,]
NA

rename columns


phs_v2 <- rename(phs_v1, replace = c(`Reference area` = "Reference_area", `Frequency of observation` = "Freq_of_obs_phs", `Unit of measure` = "Unit_of_measure_phs", `Health status` = "Health_status", "OBS_VALUE" = "OBS_VALUE_PHS"))

el_v2 <- rename(el_v1, replace = c(`Reference area` = "Reference_area", `Frequency of observation` = "Freq_of_obs_el", `Unit of measure` = "Unit_of_measure_el", `Educational attainment level` = "Edu_attainment_lvl", "OBS_VALUE" = "OBS_VALUE_EL"))

safety_v2 <- rename(safety_v1, replace = c(`Reference area` = "Reference_area", `Frequency of observation` = "Freq_of_obs_sfty", `Unit of measure` = "Unit_of_measure_sfty", "Measure" = "Measure_safety", "OBS_VALUE" = "OBS_VALUE_SAFETY", "MEASURE" = "MEASURE_SAFETY"))

social_support_or_lack_v2 <- rename(social_support_or_lack_v1, replace = c(`Reference area` = "Reference_area", `Unit of measure` = "Unit_of_measure_social", "Measure" = "Measure_social", "OBS_VALUE" = "OBS_VALUE_SOCIAL", "MEASURE" = "MEASURE_SOCIAL"))

lonely_v2 <- rename(lonely_v1, replace = c(`Reference area` = "Reference_area", "OBS_VALUE" = "OBS_VALUE_LONELY", "Measure" = "Measure_lonely", "MEASURE" = "MEASURE_LONELY"))

satisfaction_life_rels_v2 <- rename(satisfaction_life_rels_v1, replace = c(`Reference area` = "Reference_area", "OBS_VALUE" = "OBS_VALUE_SAT", "Measure" = "Measure_sat", "MEASURE" = "MEASURE_SAT"))
satisfaction_life_rels_v2[1:2,]

drop columns not anticipated to be needed or subset only the columns I will require

# Columns to keep

phs_columns_to_keep <- c("REF_AREA", "Reference_area", "TIME_PERIOD", "OBS_VALUE_PHS", "Health_status", "HEALTH_STATUS")
el_columns_to_keep <- c("REF_AREA", "Reference_area", "TIME_PERIOD", "OBS_VALUE_EL", "Edu_attainment_lvl", "ATTAINMENT_LEV")
safety_columns_to_keep <- c("REF_AREA", "Reference_area", "TIME_PERIOD", "OBS_VALUE_SAFETY", "Measure_safety", "MEASURE_SAFETY")
social_columns_to_keep <- c("REF_AREA", "Reference_area", "TIME_PERIOD", "OBS_VALUE_SOCIAL", "Measure_social", "MEASURE_SOCIAL")
lonely_columns_to_keep <- c("REF_AREA", "Reference_area", "TIME_PERIOD", "OBS_VALUE_LONELY", "Measure_lonely", "MEASURE_LONELY")
satisfaction_columns_to_keep <- c("REF_AREA", "Reference_area", "TIME_PERIOD", "OBS_VALUE_SAT", "Measure_sat", "MEASURE_SAT")

phs_v3 <- subset(phs_v2, select = phs_columns_to_keep)
el_v3 <- subset(el_v2, select = el_columns_to_keep)
safety_v3 <- subset(safety_v2, select = safety_columns_to_keep)
social_support_or_lack_v3 <- subset(social_support_or_lack_v2, select = social_columns_to_keep)
lonely_v3 <- subset(lonely_v2, select = lonely_columns_to_keep)
satisfaction_life_rels_v3 <- subset(satisfaction_life_rels_v2, select = satisfaction_columns_to_keep)

phs_v3

el_v3

safety_v3

social_support_or_lack_v3

lonely_v3

satisfaction_life_rels_v3
NA

Pivot all data sets prior to merging them.


phs_pivoted <- phs_v3 %>% 
  pivot_wider(
    id_cols = c("REF_AREA", "Reference_area", "TIME_PERIOD"), 
    names_from = c("HEALTH_STATUS"),
    names_prefix = "health_status_",
    values_from = "OBS_VALUE_PHS"
    )

phs_pivoted
NA

el_pivoted <- el_v3 %>% 
  pivot_wider(
    id_cols = c("REF_AREA", "Reference_area", "TIME_PERIOD"), 
    names_from = c("Edu_attainment_lvl"),
    values_from = "OBS_VALUE_EL"
    )


el_pivoted
NA

safety_pivoted <- safety_v3 %>% 
  pivot_wider(
    id_cols = c("REF_AREA", "Reference_area", "TIME_PERIOD"), 
    names_from = c("Measure_safety"),
    values_from = "OBS_VALUE_SAFETY"
    )


safety_pivoted
NA

social_support_or_lack_pivoted <- social_support_or_lack_v3 %>% 
  pivot_wider(
    id_cols = c("REF_AREA", "Reference_area", "TIME_PERIOD"), 
    names_from = c("Measure_social"),
    values_from = "OBS_VALUE_SOCIAL"
    )

social_support_or_lack_pivoted
NA

lonely_pivoted <- lonely_v3 %>% 
  pivot_wider(
    id_cols = c("REF_AREA", "Reference_area", "TIME_PERIOD"), 
    names_from = c("Measure_lonely"),
    values_from = "OBS_VALUE_LONELY"
    )

lonely_pivoted
NA

satisfaction_life_rels_pivoted <- satisfaction_life_rels_v3 %>% 
  pivot_wider(
    id_cols = c("REF_AREA", "Reference_area", "TIME_PERIOD"), 
    names_from = c("Measure_sat"),
    values_from = "OBS_VALUE_SAT"
    )

satisfaction_life_rels_pivoted
NA

Merge all 6 data sets


phs_el <- merge(
  phs_pivoted,
  el_pivoted,
  by = c("REF_AREA", "Reference_area", "TIME_PERIOD"),
  all = TRUE
)

phs_el
NA

phs_el_safety <- merge(
  phs_el,
  safety_pivoted,
  by = c("REF_AREA", "Reference_area", "TIME_PERIOD"),
  all = TRUE
)

phs_el_safety
NA

phs_el_safety_social <- merge(
  phs_el_safety,
  social_support_or_lack_pivoted,
  by = c("REF_AREA", "Reference_area", "TIME_PERIOD"),
  all = TRUE
)

phs_el_safety_social
NA

phs_el_safety_social_lonely <- merge(
  phs_el_safety_social,
  lonely_pivoted,
  by = c("REF_AREA", "Reference_area", "TIME_PERIOD"),
  all = TRUE
)

phs_el_safety_social_lonely
NA

phs_el_safety_social_lonely_satisfaction <- merge(
  phs_el_safety_social_lonely,
  satisfaction_life_rels_pivoted,
  by = c("REF_AREA", "Reference_area", "TIME_PERIOD"),
  all = TRUE
)

phs_el_safety_social_lonely_satisfaction
NA

Use fill from tidyr to fill, up and down, the lonely data


phs_el_safety_social_lonely_satisfaction_fill <- phs_el_safety_social_lonely_satisfaction |>
  group_by(Reference_area) |>
  fill(`Feeling lonely`, .direction = "updown") |>
  ungroup()

phs_el_safety_social_lonely_satisfaction_fill
NA

phs_el_safety_social_lonely_satisfaction_filled <- phs_el_safety_social_lonely_satisfaction_fill |>
  group_by(Reference_area) |>
  fill(`Satisfaction with personal relationships`, .direction = "updown") |>
  ungroup()

phs_el_safety_social_lonely_satisfaction_filled
NA

df <- phs_el_safety_social_lonely_satisfaction_filled |>
  group_by(Reference_area) |>
  fill(`Life satisfaction`, .direction = "updown") |>
  ungroup()

df
NA

Final version of the dataset to be used in the shiny app.


df %>% view()
# write.csv(df, file = "../data/df.csv")
hist(df$`Feeling lonely`, xlab="lonely")


sort(unique(df$`Feeling lonely`))
 [1]  3.131366  3.444549  3.470850  3.500000  3.589915  3.600000  3.817022
 [8]  3.857592  3.909297  4.000000  4.044682  4.068202  4.179466  4.186444
[15]  4.254773  4.286276  4.444873  4.500000  4.525158  4.800000  4.850588
[22]  4.900000  4.947824  5.105207  5.129866  5.183457  5.233685  5.259631
[29]  5.313834  5.327242  5.380740  5.401067  5.445733  5.549899  5.573010
[36]  5.658739  5.658772  5.664709  5.927277  6.095523  6.244574  6.295952
[43]  6.300000  6.400000  6.440687  6.466081  6.616622  6.659974  6.953202
[50]  7.027851  7.088179  7.137664  7.167792  7.193489  7.280727  7.592857
[57]  7.850135  8.061958  8.135317  8.136483  8.329389  8.579049  8.850272
[64]  8.921706  9.214390  9.330003  9.332626  9.348542 10.773153 12.860000
[71] 13.420000 13.850000
class(df)
[1] "tbl_df"     "tbl"        "data.frame"
max(df$`Feeling lonely`, na.rm = TRUE)
[1] 13.85
df %>% view()
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KTGlicmFyaWVzIEkgbWF5IHVzZSBjYWxsZWQNCmBgYHtyfQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCiMgaW5zdGFsbCBmb3IgdmlzdWFsaXphdGlvbnMgDQpsaWJyYXJ5KGdncGxvdDIpDQojIGluc3RhbGwgdG8gY29tYmluZSBkYXRlIGFuZCB0aW1lDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCiMgZm9yIG1lbHRpbmcgYSBkZg0KbGlicmFyeShyZXNoYXBlKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KDQpgYGANCiMjIyBQZXJjZWl2ZWQgSGVhbHRoIFN0YXR1cw0KDQpSZWFkaW5nIGluIHRoZSBmaXJzdCBkYXRhc2V0LCBwZXJjZWl2ZWQgaGVhbHRoIHN0YXR1cy4NCiANCmBgYHtyfQ0KcGVyY2VpdmVkX2hlYWx0aF9zdGF0dXMgPC0gcmVhZF9jc3YoIi4uL2RhdGEvcGVyY2VpdmVkX2hlYWx0aF9zdGF0dXMuY3N2IikNCiMgZG5tayA8LSByZWFkX2NzdigiLi4vZGF0YS9kZW5tYXJrX29ubHlfcGhzLmNzdiIpDQojIHBlcmNlaXZlZF9oZWFsdGhfc3RhdHVzX29uY2UgPC0gcmVhZF9jc3YoIi4uL2RhdGEvcGVyY2VpdmVkX2hlYWx0aF9zdGF0dXNfb25jZS5jc3YiKQ0KDQpgYGANCkluc3BlY3RpbmcgdGhlIGRlbm1hcmsgb25seSBkYXRhOg0KDQpgYGB7cn0NCiMgZG5tayAlPiUgDQojICAgZmlsdGVyKFNleCA9PSAiVG90YWwiKQ0KYGBgDQoNCkl0IGFwcGVhcnMgdGhhdCB0aGVuIA0KDQoNCkluc3BlY3RpbmcgdGhlIHBlcmNlaXZlZCBoZWFsdGggZGF0YToNCg0KYGBge3J9DQpwZXJjZWl2ZWRfaGVhbHRoX3N0YXR1cyAlPiUgDQogIGZpbHRlcihgUmVmZXJlbmNlIGFyZWFgID09ICJEZW5tYXJrIikNCmBgYA0KDQpJbnNwZWN0IG9yaWdpbmFsIHBlcmNlaXZlZCBoZWFsdGggZGF0YToNCmBgYHtyfQ0KIyBwZXJjZWl2ZWRfaGVhbHRoX3N0YXR1c19vbmNlJT4lIA0KIyAgIGZpbHRlcihgUmVmZXJlbmNlIGFyZWFgID09ICJEZW5tYXJrIikNCmBgYA0KYGBge3J9DQpwZXJjZWl2ZWRfaGVhbHRoX3N0YXR1cw0KYGBgDQoNCg0KRmlsdGVyaW5nLg0KDQpgYGB7cn0NCg0KcGVyY2VpdmVkX2hlYWx0aF9zdGF0dXNfc3RyaXBwZWQgPC0gcGVyY2VpdmVkX2hlYWx0aF9zdGF0dXMgJT4lIA0KICBmaWx0ZXIoVElNRV9QRVJJT0QgPT0gMjAyMikgJT4lIA0KICBmaWx0ZXIoUkVGX0FSRUEgPT0gIkFVVCIpICU+JSANCiAgZmlsdGVyKFNleCA9PSAiVG90YWwiKSAlPiUgDQogIGZpbHRlcihBZ2UgPT0gIjE1IHllYXJzIG9yIG92ZXIiKSAgDQoNCnBlcmNlaXZlZF9oZWFsdGhfc3RhdHVzX3N0cmlwcGVkDQoNCmBgYA0KQXMgaXQgYXBwZWFycyB0aGF0IGFmdGVyIDIwMDcsIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGFyZSBtb3JlIHNpZ25pZmljYW50IGluIG51bWJlciwgSSB3aWxsIGxpbWl0IG15IGRhdGEgdG8gMjAwNyBhbmQgbGF0ZXIuIEJ1dCwgc2luY2UgaXQgYXBwZWFycyB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBkcm9wcyBvZmYgaW4gMjAyNCwgSSB3aWxsIGxpbWl0IG15IGRhdGEgdG8gYSByYW5nZSBvZiAyMDA3LTIwMjMuIEFzIHdlbGwsIEkgd2FudCB0byBjYXB0dXJlIGFsbCBnZW5kZXJzIGFuZCBhZ2VzLiAoQ29ycmVjdGVkICI9PSIgdG8gYmUgIiVpbiUiIGFuZCB0aGF0IGNvcnJlY3RlZCBtdWNoIHRoZSBwcm9ibGVtIEkgd2FzIHJ1bm5pbmcgaW50by4pDQoNCmBgYHtyfQ0KDQojIGlucHV0IGNvZGUgdG8gbGltaXQgeWVhciByYW5nZSwgYWdlIHJhbmdlLCBhbmQgZ2VuZGVyIGluIHBlcmNlaXZlZCBoZWFsdGggc3RhdHVzIGRhdGENCg0KcGhzIDwtIHBlcmNlaXZlZF9oZWFsdGhfc3RhdHVzICU+JSANCiAgZmlsdGVyKFRJTUVfUEVSSU9EICVpbiUgYygyMDA3OjIwMjMpKSAlPiUgDQogIGZpbHRlcihTZXggPT0gIlRvdGFsIikgJT4lIA0KICBmaWx0ZXIoQWdlID09ICIxNSB5ZWFycyBvciBvdmVyIikNCg0KcGhzDQoNCmBgYA0KSXQgdHVybnMgb3V0IHRoYXQgRGVubWFyaydzIGRhdGEgY29tZXMgb25seSBmcm9tIGEgcG9wdWxhdGlvbiBvZiAxNS0yNCB5ZWFyIG9sZCwgd2hpY2ggd291bGQgYmUgZXhjbHVkZWQgd2hlbiBJIGZpbHRlciBmb3IgYWdlIHJhbmdlIGNvbGxlY3RpdmUvVG90YWwuIChDb3JyZWN0ZWQgIj09IiB0byBiZSAiJWluJSIgd2hpY2ggY29ycmVjdGVkIHdoYXQgSSB3YXMgc2VlaW5nLikNCg0KYGBge3J9DQoNCiMgcGVyY2VpdmVkX2hlYWx0aF9zdGF0dXNfb25jZSAlPiUgDQojICAgZmlsdGVyKFRJTUVfUEVSSU9EICVpbiUgYygyMDA3OjIwMjMpKSAlPiUgDQojICAgZmlsdGVyKFNleCA9PSAiVG90YWwiKSAlPiUgDQojICAgZmlsdGVyKEFHRSA9PSAiWV9HRTE1IikgDQoNCmBgYA0KDQpgYGB7cn0NCg0KIyBzb3J0KHVuaXF1ZShwZXJjZWl2ZWRfaGVhbHRoX3N0YXR1c19vbmNlJEFnZSkpDQojIA0KIyBwZXJjZWl2ZWRfaGVhbHRoX3N0YXR1c19vbmNlICU+JSANCiMgICBncm91cF9ieShBR0UpICU+JQ0KIyAgIHN1bW1hcml6ZShuPW4oKSkNCg0KYGBgDQoNCg0KSW5zcGVjdCB0aGUgZGF0YSBmb3IgdGhlIG51bWJlciBvZiB5ZWFycyBpdCBjb3ZlcnMuDQoNCmBgYHtyfQ0KDQpiYXJwbG90KHRhYmxlKHBlcmNlaXZlZF9oZWFsdGhfc3RhdHVzJFRJTUVfUEVSSU9EKSwgbWFpbiA9ICJudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIG9mIHllYXIgaW4gdGhlIGRhdGEiKQ0KDQoNCmBgYA0KDQpJbnNwZWN0IHRoZSBkYXRhIGZvciB0aGUgbnVtYmVyIG9mIGFnZSBjYXRlZ29yaWVzIGl0IGNvdmVycy4NCmBgYHtyfQ0KYmFycGxvdCh0YWJsZShwZXJjZWl2ZWRfaGVhbHRoX3N0YXR1cyRBZ2UpLCBtYWluID0gIm51bWJlciBvZiBvYnNlcnZhdGlvbnMgb2YgYWdlIGdyb3VwcyBpbiB0aGUgZGF0YSIpDQpgYGANCg0KSW5zcGVjdGluZyB0aGUgZGF0YSBmb3IgYmFsYW5jZSBpbiB0aGUgaGVhbHRoIHN0YXR1cyBjb2x1bW4uDQoNCmBgYHtyfQ0KDQpwaHMgJT4lIA0KICBncm91cF9ieShIRUFMVEhfU1RBVFVTKSAlPiUgDQogIHN1bW1hcml6ZShuPW4oKSkNCg0KYGBgDQoNCldoaWNoIGNvdW50cmllcyBhcmUgbW9zdCBoZWF2aWx5IHJlcHJlc2VudGVkIGluIHRoZSBkYXRhPyBEZW5tYXJrIHdhcyBzZWxlY3RlZCB0byBiZSBpbmNsdWRlZCBJIHdpbGwgZG93bmxvYWQgYSBEZW5tYXJrIG9ubHkgZGF0YSBhbmQgaW52ZXN0aWdhdGUgd2h5IGl0IGlzIG5vIGxvbmdlciBsb2NhdGVkIGluIHRoaXMgZGF0YS4gDQoNCmBgYHtyfQ0KDQpwaHMgJT4lIA0KICBncm91cF9ieShgUmVmZXJlbmNlIGFyZWFgKSAlPiUNCiAgc3VtbWFyaXplKG49bigpKQ0KDQpgYGANCg0KYGBge3J9DQpwaHMgJT4lIA0KICBncm91cF9ieShBR0UpICU+JQ0KICBzdW1tYXJpemUobj1uKCkpDQoNCmBgYA0KDQpUaGUgZmluYWwgc3RhdGUgb2YgbXkgUGVyY2VpdmVkIEhlYWx0aCBTdGF0dXMgZGF0YSB3aWxsIGJlOg0KYGBge3J9DQoNCnBocw0KDQpgYGANCg0KDQoNCiMjIyBFZHVjYXRpb24gTGV2ZWxzDQoNCg0KDQpSZWFkaW5nIGluIHRoZSBzZWNvbmQgZGF0YXNldCwgZWR1Y2F0aW9uIGxldmVscy4NCg0KYGBge3J9DQoNCiMgZWR1Y2F0aW9uX2xldmVsIDwtIHJlYWRfY3N2KCIuLi9kYXRhL2VkdWNhdGlvbmFsX2F0dGFpbm1lbnRfZGlzdHJpYnV0aW9uX2FnZV9nZW5kZXIuY3N2IikNCiMgZWR1Y2F0aW9uX2xldmVsc19kZWZpbmVkIDwtIHJlYWRfY3N2KCIuLi9kYXRhL2VkdWNhdGlvbmFsX2F0dGFpbm1lbnRfZGlzdHJpYnV0aW9uLmNzdiIpDQplZHVjYXRpb25fbGV2ZWxzX3RocmVlIDwtIHJlYWRfY3N2KCIuLi9kYXRhL2VkdWNhdGlvbmFsX2F0dGFpbm1lbnQuY3N2IikNCg0KYGBgDQoNCkVhcmx5IGRhdGEgZXhwbG9yYXRpb24gaW4gdGhlIGVkdWNhdGlvbiBkYXRhDQoNCmBgYHtyfQ0KZWxfdGhpcmQgPC0gZWR1Y2F0aW9uX2xldmVsc190aHJlZSAlPiUgDQogIGZpbHRlcihTZXggPT0gIlRvdGFsIikgJT4lIA0KICBmaWx0ZXIoQWdlID09ICJGcm9tIDI1IHRvIDY0IHllYXJzIikgJT4lIA0KICBmaWx0ZXIoVElNRV9QRVJJT0QgPT0gMjAxMCkgJT4lIA0KICBmaWx0ZXIoT0JTX1NUQVRVUyA9PSAiQSIpICU+JSANCiAgZmlsdGVyKFJFRl9BUkVBID09ICJBVVQiKSAlPiUgDQogIGZpbHRlcihTVEFUSVNUSUNBTF9PUEVSQVRJT04gPT0gIk9CUyIpDQoNCmVsX3RoaXJkDQpgYGANCg0KDQpgYGB7cn0NCg0KIyBJU0NFRDExQV81VDggPSBUZXJ0aWFyeSBlZHVjYXRpb24NCiMgSVNDRUQxMUFfM180ID0gVXBwZXIgc2Vjb25kYXJ5IG9yIHBvc3Qtc2Vjb25kYXJ5IG5vbi10ZXJ0aWFyeSBlZHVjYXRpb24NCiMgSVNDRUQxMUFfMFQyID0gQmVsb3cgdXBwZXIgc2Vjb25kYXJ5IGVkdWNhdGlvbg0KZWR1Y2F0aW9uX2xldmVsc190aHJlZQ0KDQpgYGANClZlcmlmeSB0aGF0IHRoZXJlIGFyZSBzaW1wbHkgdGhyZWUgY2F0ZWdvcmllcyBmb3IgdGhlIGVkdWNhdGlvbiBsZXZlbCBhdHRhaW5lZCBhbmQgIEVkdWNhdGlvbiBhdHRhaW5tZW50IGxldmVsIGNvbHVtbnMNCmBgYHtyfQ0KDQpzb3J0KHVuaXF1ZShlZHVjYXRpb25fbGV2ZWxzX3RocmVlJEFUVEFJTk1FTlRfTEVWKSkNCnNvcnQodW5pcXVlKGVkdWNhdGlvbl9sZXZlbHNfdGhyZWUkYEVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgbGV2ZWxgKSkNCg0KYGBgDQoNCmBgYHtyfQ0Kc29ydCh1bmlxdWUoZWR1Y2F0aW9uX2xldmVsc190aHJlZSRTVEFUSVNUSUNBTF9PUEVSQVRJT04pKQ0KYGBgDQpJIHdhbnQgdG8gdXNlIHRoZSBvYnNlcnZlZCB2YWx1ZXMgYW5kIG5vdCB0aGUgc3RhbmRhcmQgZXJyb3IgdmFsdWVzIGF0IHRoaXMgdGltZS4gDQpgYGB7cn0NCg0KZWR1Y2F0aW9uX2xldmVsc190aHJlZSAlPiUgDQogIGZpbHRlcihTVEFUSVNUSUNBTF9PUEVSQVRJT04gPT0gIk9CUyIpDQoNCmBgYA0KDQpJIHdhbnQgdG8gc2VlIHRoZSByZXByZXNlbnRhdGlvbiBvZiBjb3VudHJpZXMgaW4gdGhlIGRhdGEuIENlcnRhaW4gY291bnRyaWVzIGFyZSBzaWduaWZpY2FudGx5IHVuZGVyIHJlcHJlc2VudGVkLg0KDQpgYGB7cn0NCmJhcnBsb3QodGFibGUoZWR1Y2F0aW9uX2xldmVsc190aHJlZSRgUmVmZXJlbmNlIGFyZWFgKSwgbWFpbiA9ICJudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIG9mIGNvdW50cmllcyBpbiB0aGUgZGF0YSIpDQoNCmBgYA0KDQpgYGB7cn0NCmJhcnBsb3QodGFibGUoZWR1Y2F0aW9uX2xldmVsc190aHJlZSRUSU1FX1BFUklPRCksIG1haW4gPSAibnVtYmVyIG9mIG9ic2VydmF0aW9ucyBvZiB5ZWFyIGluIHRoZSBkYXRhIikNCg0KYGBgDQoNCmNoZWNrIHRvIHNlZSB3aGljaCB5ZWFycyBhcmUgcHJlc2VudCBpbiB0aGUgZGF0YS4gQmFzZSBvbiB0aGUgbGFjayBvZiBkYXRhIGluIHRoZSB5ZWFycyBwcmlvciB0byBhYm91dCAxOTk4LCBJIHdpbGwgbGltaXQgdGhlIGRhdGFzZXQgdG8gMTk5OC0yMDI0Lg0KDQpgYGB7cn0NCg0Kc29ydCh1bmlxdWUoZWR1Y2F0aW9uX2xldmVsc190aHJlZSRUSU1FX1BFUklPRCkpDQoNCmVkdWNhdGlvbl9sZXZlbHNfdGhyZWVfdGltZSA8LSBlZHVjYXRpb25fbGV2ZWxzX3RocmVlICU+JSANCiAgZmlsdGVyKFRJTUVfUEVSSU9EICVpbiUgYygxOTk4OjIwMjQpKQ0KDQpgYGANCg0KSSB3b3VsZCBsaWtlIHRvIGRpc2NvdmVyIHdoaWNoIG9mIHRoZSBjb3VudHJpZXMgYXJlIHVuZGVyIHJlcHJlc2VudGVkLiANCg0KYGBge3J9DQplZHVjYXRpb25fbGV2ZWxzX3RocmVlX3RpbWUgJT4lIA0KICBncm91cF9ieShgUmVmZXJlbmNlIGFyZWFgKSAlPiUNCiAgc3VtbWFyaXplKG49bigpKQ0KYGBgDQoNCg0KSSB3YW50IHRvIGRyb3AgYW55IGNvdW50cmllcyB3aG9zZSBjb3VudCBpcyBsZXNzIHRoYW4gMTgwMC4gDQoNCmBgYHtyfQ0KDQojIGNvdW50IHRoZSBmcmVxdWVuY3kgb2YgZWFjaCBjb3VudHJ5DQpjb3VudHJ5X2NvdW50IDwtIHRhYmxlKGVkdWNhdGlvbl9sZXZlbHNfdGhyZWVfdGltZSRgUmVmZXJlbmNlIGFyZWFgKQ0KDQojIEkgZG8gbm90IHdhbnQgYW55IGZld2VyIHJvd3MgZm9yIGEgY291bnRyeSB0aGFuIHRoaXMNCm51bV9pbl9kYXRhIDwtIDE4MDANCg0KIyB3aGljaCBjb3VudHJpZXMgbWF0Y2ggb3IgZXhjZWVkIHRoYXQgbnVtYmVyDQpjb3VudHJpZXNfdG9fa2VlcCA8LSBuYW1lcyhjb3VudHJ5X2NvdW50W2NvdW50cnlfY291bnQgPiBudW1faW5fZGF0YV0pDQoNCiMgZmlsdGVyIHRoZSBkYXRhc2V0IHRvIGtlZXAgb25seSByb3dzIG9mIGNvdW50cmllcyB3aG8gYXJlIA0KI3JlcHJlc2VudGVkIGluIHRoZSBkYXRhIGEgY2VydGFpbiBudW1iZXIgb2YgdGltZXMgb3IgbW9yZQ0KZWR1Y2F0aW9uX2xldmVsc190aHJlZV90aW1lX2NvdW50cmllcyA8LSBlZHVjYXRpb25fbGV2ZWxzX3RocmVlX3RpbWVbZWR1Y2F0aW9uX2xldmVsc190aHJlZV90aW1lJGBSZWZlcmVuY2UgYXJlYWAgJWluJSBjb3VudHJpZXNfdG9fa2VlcCwgXQ0KDQplZHVjYXRpb25fbGV2ZWxzX3RocmVlX3RpbWVfY291bnRyaWVzIA0KDQoNCmBgYA0KDQpDaGVjayBvdXQgd2hpY2ggYWdlcyBhcmUgYXZhaWxhYmxlIHRvIGZpbHRlciBieS4NCg0KYGBge3J9DQpzb3J0KHVuaXF1ZShlZHVjYXRpb25fbGV2ZWxzX3RocmVlX3RpbWVfY291bnRyaWVzJEFnZSkpDQpgYGANCg0KQ2hlY2sgbnVtYmVyIG9mIHRpbWVzIGVhY2ggYWdlIHJhbmdlIGlzIHJlcHJlc2VudGVkIGluIHRoZSBkYXRhDQpgYGB7cn0NCg0KYmFycGxvdCh0YWJsZShlZHVjYXRpb25fbGV2ZWxzX3RocmVlX3RpbWVfY291bnRyaWVzJEFnZSksIG1haW4gPSAibnVtYmVyIG9mIG9ic2VydmF0aW9ucyBvZiBhZ2UgaW4gdGhlIGRhdGEiKQ0KDQoNCmBgYA0KDQoNCkZpbHRlciB1c2luZyBhbGwgb2YgdGhlIG1ldGhvZHMgbGVmdCB0aGF0IEkgd2FudCB0byBmaWx0ZXIgYnk6IGFsbCBnZW5kZXJzLCBhZ2VzLCBhcyB3ZWxsIGFzIG9ubHkgb2JzZXJ2ZWQgZGF0YSwgbm90IHRoZSBzdGFuZGFyZCBlcnJvci4NCg0KYGBge3J9DQoNCmVsIDwtIGVkdWNhdGlvbl9sZXZlbHNfdGhyZWVfdGltZV9jb3VudHJpZXMgJT4lIA0KICBmaWx0ZXIoU2V4ID09ICJUb3RhbCIpICU+JSANCiAgZmlsdGVyKEFnZSA9PSAiRnJvbSAyNSB0byA2NCB5ZWFycyIpICU+JSANCiAgZmlsdGVyKE9CU19TVEFUVVMgPT0gIkEiKSAlPiUNCiAgZmlsdGVyKFNUQVRJU1RJQ0FMX09QRVJBVElPTiA9PSAiT0JTIikNCg0KYGBgDQoNCmBgYHtyfQ0KZWwNCmBgYA0KDQoNClRoZSBmaW5hbCBzdGF0ZSBvZiBteSBlZHVjYXRpb24gbGV2ZWwgZGF0YSB3aWxsIGJlOg0KDQpgYGB7cn0NCg0KIyBzZWxlY3RlZCBhbGwgYWR1bHRzIGZyb20gYWdlLCBhbmQgYWxsIGdlbmRlcnMsIGFuZCBvbmx5IG9ic2VydmVkIHZhbHVlcyBubyBzdGFuZGFyZCBlcnJvciB2YWx1ZXMNCmVsWzE6MixdDQoNCmBgYA0KDQoNCg0KDQoNCg0KIyMjIFNvY2lhbCBhbmQgQ29tbXVuaXR5IGNvbm5lY3Rpb24gcHVsbGVkIGZyb20gdGhlIFdlbGxiZWluZyBkYXRhc2V0DQoNCg0KDQoNCg0KUmVhZGluZyBpbiB0aGUgdGhpcmQgZGF0YXNldCwgc29jaWFsIGNvbm5lY3RlZG5lc3MgZnJvbSB0aGUgd2VsbGJlaW5nIGRhdGFzZXQuDQoNCg0KYGBge3J9DQoNCnNvY2lhbF93ZWxsYmVpbmcgPC0gcmVhZF9jc3YoIi4uL2RhdGEvc29jaWFsX2Nvbm5lY3Rpb25fd2VsbGJlaW5nLmNzdiIpDQoNCmBgYA0KDQpWaWV3IHRoZSBkYXRhLg0KYGBge3J9DQpzb2NpYWxfd2VsbGJlaW5nWzE6MiwgXQ0KYGBgDQoNCkluc3BlY3QgdGhlIFVOSVRfTUVBU1VSRSBjb2x1bW4ncyB1bmlxdWUgdmFsdWVzLg0KYGBge3J9DQoNCnNvcnQodW5pcXVlKHNvY2lhbF93ZWxsYmVpbmckVU5JVF9NRUFTVVJFKSkNCg0KYGBgDQpgYGB7cn0NCg0Kc29ydCh1bmlxdWUoc29jaWFsX3dlbGxiZWluZyRNZWFzdXJlKSkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCnNvY2lhbF93ZWxsYmVpbmcgJT4lIA0KICBmaWx0ZXIoVElNRV9QRVJJT0QgPT0gMjAyMikgJT4lIA0KICBmaWx0ZXIoUkVGX0FSRUEgPT0gIkFVUyIpICU+JSANCiAgZmlsdGVyKE1lYXN1cmUgJWluJSBjKCJTb2NpYWwgc3VwcG9ydCIsICJMYWNrIG9mIHNvY2lhbCBzdXBwb3J0IikpICU+JSANCiAgZmlsdGVyKFNleCA9PSAiVG90YWwiKSAlPiUgDQogIGZpbHRlcihBZ2UgPT0gIlRvdGFsIikgJT4lIA0KICBmaWx0ZXIoYEVkdWNhdGlvbiBsZXZlbGAgPT0gIlRvdGFsIikNCg0KYGBgDQpBc3NpZ25pbmcgZmlsdGVyZWQgZGF0YXNldCB0byBuZXcgdmFyaWFibGUuDQoNCmBgYHtyfQ0KDQpzb2NpYWxfc3VwcG9ydF9vcl9sYWNrIDwtIHNvY2lhbF93ZWxsYmVpbmcgJT4lIA0KICBmaWx0ZXIoVElNRV9QRVJJT0QgJWluJSBjKDIwMDc6MjAyMykpICU+JSANCiAgZmlsdGVyKE1lYXN1cmUgJWluJSBjKCJTb2NpYWwgc3VwcG9ydCIsICJMYWNrIG9mIHNvY2lhbCBzdXBwb3J0IikpICU+JSANCiAgZmlsdGVyKFNleCA9PSAiVG90YWwiKSAlPiUgDQogIGZpbHRlcihBZ2UgPT0gIlRvdGFsIikgJT4lIA0KICBmaWx0ZXIoYEVkdWNhdGlvbiBsZXZlbGAgPT0gIlRvdGFsIikNCg0Kc29jaWFsX3N1cHBvcnRfb3JfbGFja1sxOjIsIF0NCg0KYGBgDQoNCg0KYGBge3J9DQoNCmJhcnBsb3QodGFibGUoc29jaWFsX3N1cHBvcnRfb3JfbGFjayRUSU1FX1BFUklPRCksIG1haW4gPSAiZnJlcXVlbmN5IG9mIHllYXJzIGluIHRoZSBkYXRhIikNCg0KYGBgDQoNCg0KYGBge3J9DQoNCiMgZmluZCB1bmlxdWUgdmFsdWVzIGZvciBNZWFzdXJlIGNvbHVtbg0Kc29ydCh1bmlxdWUoc29jaWFsX3dlbGxiZWluZyRNZWFzdXJlKSkNCg0KDQpgYGANCkhvdyBpcyBzYXRpc2ZhY3Rpb24gd2l0aCBwZXJzb25hbCByZWxhdGlvbnNoaXBzIHNjb3JlZD8NCg0KYGBge3J9DQpzb2NpYWxfd2VsbGJlaW5nICU+JSANCiAgZmlsdGVyKE1lYXN1cmUgPT0gIlNhdGlzZmFjdGlvbiB3aXRoIHBlcnNvbmFsIHJlbGF0aW9uc2hpcHMgc2NvcmUgbGVzcyB0aGFuIDUiKQ0KYGBgDQoNCkluc3BlY3Qgd2hpY2ggTWVhc3VyZXMgYXJlIGxpc3RlZCB3aXRoIHRoZSAwIHRvIDEwIHVuaXQgbWVhc3VyZS4NCg0KYGBge3J9DQoNCnNvY2lhbF93ZWxsYmVpbmdfMF8xMCA8LSBzb2NpYWxfd2VsbGJlaW5nICU+JSANCiAgZmlsdGVyKFVOSVRfTUVBU1VSRSA9PSAiMF9UT18xMCIpDQoNCnNvY2lhbF93ZWxsYmVpbmdfMF8xMFsxOjIsIF0NCg0KYGBgDQoNCg0KYGBge3J9DQoNCnNvcnQodW5pcXVlKHNvY2lhbF93ZWxsYmVpbmdfMF8xMCRNZWFzdXJlKSkNCg0KYGBgDQoNCkxpbWl0IHRoZSBkYXRhIHRvIHRvdGFscyBvbiBzZXgsIGFnZSwgYW5kIGVkdWNhdGlvbiwgaW4gb3JkZXIgdG8gY2FwdHVyZSBhIHBvcHVsYXRpb24gbm90IGEgc3BlY2lmaWMgZ3JvdXAgd2l0aGluIGEgcG9wdWxhdGlvbi4gQXMgd2VsbCwgbmFycm93IGRvd24gdGhlIGRhdGUgcmFuZ2UgYW5kIHNlbGVjdCBvbmx5IHRoZSBNZWFzdXJlcyB3aG9zZSB1bml0IG1lYXN1cmUgaXMgMC0xMC4gDQoNCmBgYHtyfQ0KDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzIDwtIHNvY2lhbF93ZWxsYmVpbmcgJT4lIA0KICBmaWx0ZXIoVElNRV9QRVJJT0QgJWluJSBjKDIwMDc6MjAyMykpICU+JSANCiAgZmlsdGVyKE1lYXN1cmUgJWluJSBjKCJMaWZlIHNhdGlzZmFjdGlvbiIsICJTYXRpc2ZhY3Rpb24gd2l0aCBwZXJzb25hbCByZWxhdGlvbnNoaXBzIikpICU+JSANCiAgZmlsdGVyKFNleCA9PSAiVG90YWwiKSAlPiUgDQogIGZpbHRlcihBZ2UgPT0gIlRvdGFsIikgJT4lIA0KICBmaWx0ZXIoYEVkdWNhdGlvbiBsZXZlbGAgPT0gIlRvdGFsIikNCiAgDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzWzE6MiwgXQ0KDQpgYGANCmBgYHtyfQ0KDQpiYXJwbG90KHRhYmxlKHNhdGlzZmFjdGlvbl9saWZlX3JlbHMkVElNRV9QRVJJT0QpKQ0KDQpgYGANCg0KTG9va2luZyBpbnRvIHRoZSBmZWVsaW5nIGxvbmVseSBtZWFzdXJlLg0KDQpgYGB7cn0NCg0KDQpsb25lbHkgPC0gc29jaWFsX3dlbGxiZWluZyAlPiUgDQogIGZpbHRlcihUSU1FX1BFUklPRCAlaW4lIGMoMjAwNzoyMDIzKSkgJT4lICAgDQogIGZpbHRlcihNZWFzdXJlID09ICJGZWVsaW5nIGxvbmVseSIpICU+JSANCiAgZmlsdGVyKFNleCA9PSAiVG90YWwiKSAlPiUgDQogIGZpbHRlcihBZ2UgPT0gIlRvdGFsIikgJT4lIA0KICBmaWx0ZXIoYEVkdWNhdGlvbiBsZXZlbGAgPT0gIlRvdGFsIikNCiAgDQpsb25lbHlbMToyLCBdDQoNCmBgYA0KDQpgYGB7cn0NCmJhcnBsb3QodGFibGUobG9uZWx5JFRJTUVfUEVSSU9EKSwgbWFpbiA9ICJob3cgb2Z0ZW4gY2VydGFpbiB5ZWFycyBhcmUgcmVwJ2QgaW4gZGF0YSIpDQpgYGANCg0KYGBge3J9DQoNCm51bV9jb3VudHJpZXNfcmVwZF9pbl9sb25lbHkgPC0gbG9uZWx5ICU+JSANCiAgZ3JvdXBfYnkoYFJlZmVyZW5jZSBhcmVhYCkgJT4lIA0KICBzdW1tYXJpc2Uobj1uKCkpDQoNCg0KY3Ryc19kZXNjIDwtIG9yZGVyKG51bV9jb3VudHJpZXNfcmVwZF9pbl9sb25lbHkkbiwgZGVjcmVhc2luZyA9IFRSVUUpDQoNCm51bV9jb3VudHJpZXNfcmVwZF9pbl9sb25lbHlbY3Ryc19kZXNjLF1bMToyLCBdDQoNCg0KYGBgDQpgYGB7cn0NCmJhcnBsb3QodGFibGUoc29jaWFsX3N1cHBvcnRfb3JfbGFjayRUSU1FX1BFUklPRCksIG1haW4gPSAiaG93IG9mdGVuIGVhY2ggeWVhciBzaG93cyB1cCBpbiBkYXRhc2V0IiApDQpgYGANCmBgYHtyfQ0KDQpzb2NpYWxfaW50ZXJhY3Rpb25zIDwtIHNvY2lhbF93ZWxsYmVpbmcgJT4lIA0KICBmaWx0ZXIoVElNRV9QRVJJT0QgJWluJSBjKDIwMDc6MjAyMykpICU+JSAgIA0KICBmaWx0ZXIoTWVhc3VyZSA9PSAiVGltZSBzcGVudCBpbiBzb2NpYWwgaW50ZXJhY3Rpb25zIikgJT4lIA0KICBmaWx0ZXIoU2V4ID09ICJUb3RhbCIpICU+JSANCiAgZmlsdGVyKEFnZSA9PSAiVG90YWwiKSAlPiUgDQogIGZpbHRlcihgRWR1Y2F0aW9uIGxldmVsYCA9PSAiVG90YWwiKQ0KDQpzb2NpYWxfaW50ZXJhY3Rpb25zWzE6MiwgXQ0KDQpgYGANCmBgYHtyfQ0KYmFycGxvdCh0YWJsZShzb2NpYWxfaW50ZXJhY3Rpb25zJFRJTUVfUEVSSU9EKSkNCmBgYA0KYGBge3J9DQoNCnNvY2lhbF9pbnRlcmFjdGlvbnMgJT4lIA0KICBncm91cF9ieShgUmVmZXJlbmNlIGFyZWFgKSAlPiUgDQogIHN1bW1hcmlzZShuPW4oKSkNCg0KYGBgDQoNCg0KDQpUaGUgZmluYWwgZGF0YXNldHMgZnJvbSB3ZWxsYmVpbmcgZGF0YSBJIGhhdmUgY2hvc2VuIGFyZSBhcyBmb2xsb3dzOg0KDQpgYGB7cn0NCg0KIyBtZWFzdXJlZCBhcyBhIHBlcmNlbnRhZ2UgZm8gdGhlIGFkdWx0IHBvcHVsYXRpb24gYW5kIGlzIHdlbGwgcmVwcmVzZW50ZWQgYWNyb3NzIGFsbCB5ZWFycyBpbiBzZWxlY3RlZCBkYXRhIA0Kc29jaWFsX3N1cHBvcnRfb3JfbGFja1sxOjIsIF0NCg0KIyBtZWFzdXJlZCBhcyBhIHBlcmNlbnRhZ2Ugb2YgdGhlIGFkdWx0IHBvcHVsYXRpb24sIGFuZCBpcyBhbG1vc3QgZXhjbHVzaXZlbHkgMjAxOCBhbmQgMjAyMg0KbG9uZWx5WzE6MiwgXQ0KDQojIHllYXJzIG1vc3QgcmVwcmVzZW50ZWQgaW4gdGhlIGRhdGE6IDIwMTMsIDIwMTgsIDIwMjI7IGl0IGlzIG1lYXN1cmVkIG9uIGEgMC0xMCBzY2FsZS4gDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzWzE6MiwgXQ0KDQojIG1lYXN1cmVkIGluIHVuaXRzIG9mIGhvdXJzIHBlciB3ZWVrLCBhY3Jvc3MgdmFyaW91cyB5ZWFycywgdmVyeSBkaWZmaWN1bHQgdG8gY29tcGFyZSwgSSB3aWxsIGV4Y2x1ZGUgdGhpcyBkYXRhIGZvciBub3cNCnNvY2lhbF9pbnRlcmFjdGlvbnNbMToyLCBdDQoNCmBgYA0KDQoNCg0KDQoNCiMjIyBTYWZldHkNCg0KDQpSZWFkaW5nIGluIHRoZSBzZWNvbmQgZGF0YXNldCwgZWR1Y2F0aW9uIGxldmVscy4NCg0KDQoNCg0KDQpgYGB7cn0NCg0Kc2FmZXR5X3JlZ2lvbnMgPC0gcmVhZF9jc3YoIi4uL2RhdGEvc2FmZXR5X3JlZ2lvbnMuY3N2IikNCg0KDQpgYGANCmBgYHtyfQ0Kc2FmZXR5IDwtIHNhZmV0eV9yZWdpb25zICU+JSANCiAgZmlsdGVyKFRJTUVfUEVSSU9EICVpbiUgYygyMDA3OjIwMjMpKSAlPiUgDQogIGZpbHRlcihURVJSSVRPUklBTF9MRVZFTCA9PSAiQ1RSWSIpICU+JSANCiAgZmlsdGVyKFNleCAlaW4lIGMoIlRvdGFsIiwgIk5vdCBhcHBsaWNhYmxlIikpICU+JSANCiAgZmlsdGVyKGBPYnNlcnZhdGlvbiBzdGF0dXNgID09ICJOb3JtYWwgdmFsdWUiKQ0KDQpzYWZldHlbMToyLCBdDQoNCmBgYA0KYGBge3J9DQoNCmJhcnBsb3QodGFibGUoc2FmZXR5JE9CU19WQUxVRSksIG1haW4gPSAiZnJlcXVlbmN5IG9mIHBlcmNlbnRhZ2Ugb2YgcG9wIG1lYXN1cmVkIHVuc2FmZSBpbnN0YW5jZXMgaW4gdGhlIGRhdGEiKQ0KDQpgYGANCg0KDQpgYGB7cn0NCnNvcnQodW5pcXVlKHNhZmV0eSRgT2JzZXJ2YXRpb24gc3RhdHVzYCkpDQoNCmBgYA0KDQpUaGUgZmluYWwgZGF0YXNldCBmcm9tIHNhZmV0eSBkYXRhIEkgaGF2ZSBjaG9zZW4gYXJlIGFzIGZvbGxvd3M6DQpgYGB7cn0NCnNhZmV0eVsxOjIsXQ0KYGBgDQoNCkZpbmFsIGRhdGFzZXRzIGFyZToNCg0KYGBge3J9DQoNCiMgcGVyY2VpdmVkIGhlYWx0aCBzdGF0dXMsIHN1YmplY3RpdmUgc3VydmV5IG9mIGdvb2QsIGZhaXIsIGFuZCBiYWQgaGVhbHRoDQpwaHNbMToyLCBdDQoNCiMgc2VsZWN0ZWQgYWxsIGFkdWx0cyBmcm9tIGFnZSwgYW5kIGFsbCBnZW5kZXJzLCBhbmQgb25seSBvYnNlcnZlZCB2YWx1ZXMgbm8gc3RhbmRhcmQgZXJyb3IgdmFsdWVzDQplbFsxOjIsIF0NCg0KIyBtZWFzdXJlZCBhcyBhIHBlcmNlbnRhZ2UgZm8gdGhlIGFkdWx0IHBvcHVsYXRpb24gYW5kIGlzIHdlbGwgcmVwcmVzZW50ZWQgYWNyb3NzIGFsbCB5ZWFycyBpbiBzZWxlY3RlZCBkYXRhIA0Kc29jaWFsX3N1cHBvcnRfb3JfbGFja1sxOjIsIF0NCg0KIyBtZWFzdXJlZCBhcyBhIHBlcmNlbnRhZ2Ugb2YgdGhlIGFkdWx0IHBvcHVsYXRpb24sIGFuZCBpcyBhbG1vc3QgZXhjbHVzaXZlbHkgMjAxOCBhbmQgMjAyMg0KbG9uZWx5WzE6MiwgXQ0KDQojIHllYXJzIG1vc3QgcmVwcmVzZW50ZWQgaW4gdGhlIGRhdGE6IDIwMTMsIDIwMTgsIDIwMjI7IGl0IGlzIG1lYXN1cmVkIG9uIGEgMC0xMCBzY2FsZS4gDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzWzE6MiwgXQ0KDQojIG1lYXN1cmVkIGluIGNhc2VzIHBlciAxMDAsMDAwIHBlcnNvbnMsIHdlbGwgZGlzdHJpYnV0ZWQgYWNyb3NzIHNlbGVjdGVkIHllYXJzDQpzYWZldHlbMToyLF0NCg0KYGBgDQoNCiMjI01lcmdpbmcgZGF0YSBzZXRzIHRvZ2V0aGVyIGludG8gb25lDQoNCk9yZGVyIHRoZSBkYXRhJ3MgY291bnRyeSBjb2x1bW4gKFJFRl9BUkVBKSBhbHBoYWJldGljYWxseS4gDQoNCmBgYHtyfQ0KDQojIE9yZGVyIHRoZSBkYXRhJ3MgY291bnRyeSBjb2x1bW4gKGBSZWZlcmVuY2UgYXJlYWApIGFscGhhYmV0aWNhbGx5Lg0KDQpwaHNfdjEgPC0gcGhzW29yZGVyKHBocyRgUmVmZXJlbmNlIGFyZWFgKSxdIA0KDQplbF92MSA8LSBlbFtvcmRlcihlbCRgUmVmZXJlbmNlIGFyZWFgKSxdDQoNCnNhZmV0eV92MSA8LSBzYWZldHlbb3JkZXIoc2FmZXR5JGBSZWZlcmVuY2UgYXJlYWApLF0NCg0Kc29jaWFsX3N1cHBvcnRfb3JfbGFja192MSA8LSBzb2NpYWxfc3VwcG9ydF9vcl9sYWNrW29yZGVyKHNvY2lhbF9zdXBwb3J0X29yX2xhY2skYFJlZmVyZW5jZSBhcmVhYCksXQ0KDQpsb25lbHlfdjEgPC0gbG9uZWx5W29yZGVyKGxvbmVseSRgUmVmZXJlbmNlIGFyZWFgKSxdDQoNCnNhdGlzZmFjdGlvbl9saWZlX3JlbHNfdjEgPC0gc2F0aXNmYWN0aW9uX2xpZmVfcmVsc1tvcmRlcihzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzJGBSZWZlcmVuY2UgYXJlYWApLF0NCiANCg0KDQpwaHNfdjEgIyBwZXJjZW50YWdlIG9mIHRoZSBwb3B1bGF0aW9uDQplbF92MSAjIHBlcmNlbnRhZ2Ugb2YgdGhlIHBvcHVsYXRpb24NCnNhZmV0eV92MSAjIG1lYXN1cmVkIGluIGNhc2VzIHBlciAxMDAsMDAwIHBlcnNvbnMNCnNvY2lhbF9zdXBwb3J0X29yX2xhY2tfdjEgIyBwZXJjZW50YWdlIG9mIHRoZSBwb3B1bGF0aW9uDQpsb25lbHlfdjEgIyBwZXJjZW50YWdlIG9mIHRoZSBwb3B1bGF0aW9uDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YxWzE6MixdDQoNCmBgYA0KDQpyZW5hbWUgY29sdW1ucw0KDQpgYGB7cn0NCg0KcGhzX3YyIDwtIHJlbmFtZShwaHNfdjEsIHJlcGxhY2UgPSBjKGBSZWZlcmVuY2UgYXJlYWAgPSAiUmVmZXJlbmNlX2FyZWEiLCBgRnJlcXVlbmN5IG9mIG9ic2VydmF0aW9uYCA9ICJGcmVxX29mX29ic19waHMiLCBgVW5pdCBvZiBtZWFzdXJlYCA9ICJVbml0X29mX21lYXN1cmVfcGhzIiwgYEhlYWx0aCBzdGF0dXNgID0gIkhlYWx0aF9zdGF0dXMiLCAiT0JTX1ZBTFVFIiA9ICJPQlNfVkFMVUVfUEhTIikpDQoNCmVsX3YyIDwtIHJlbmFtZShlbF92MSwgcmVwbGFjZSA9IGMoYFJlZmVyZW5jZSBhcmVhYCA9ICJSZWZlcmVuY2VfYXJlYSIsIGBGcmVxdWVuY3kgb2Ygb2JzZXJ2YXRpb25gID0gIkZyZXFfb2Zfb2JzX2VsIiwgYFVuaXQgb2YgbWVhc3VyZWAgPSAiVW5pdF9vZl9tZWFzdXJlX2VsIiwgYEVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgbGV2ZWxgID0gIkVkdV9hdHRhaW5tZW50X2x2bCIsICJPQlNfVkFMVUUiID0gIk9CU19WQUxVRV9FTCIpKQ0KDQpzYWZldHlfdjIgPC0gcmVuYW1lKHNhZmV0eV92MSwgcmVwbGFjZSA9IGMoYFJlZmVyZW5jZSBhcmVhYCA9ICJSZWZlcmVuY2VfYXJlYSIsIGBGcmVxdWVuY3kgb2Ygb2JzZXJ2YXRpb25gID0gIkZyZXFfb2Zfb2JzX3NmdHkiLCBgVW5pdCBvZiBtZWFzdXJlYCA9ICJVbml0X29mX21lYXN1cmVfc2Z0eSIsICJNZWFzdXJlIiA9ICJNZWFzdXJlX3NhZmV0eSIsICJPQlNfVkFMVUUiID0gIk9CU19WQUxVRV9TQUZFVFkiLCAiTUVBU1VSRSIgPSAiTUVBU1VSRV9TQUZFVFkiKSkNCg0Kc29jaWFsX3N1cHBvcnRfb3JfbGFja192MiA8LSByZW5hbWUoc29jaWFsX3N1cHBvcnRfb3JfbGFja192MSwgcmVwbGFjZSA9IGMoYFJlZmVyZW5jZSBhcmVhYCA9ICJSZWZlcmVuY2VfYXJlYSIsIGBVbml0IG9mIG1lYXN1cmVgID0gIlVuaXRfb2ZfbWVhc3VyZV9zb2NpYWwiLCAiTWVhc3VyZSIgPSAiTWVhc3VyZV9zb2NpYWwiLCAiT0JTX1ZBTFVFIiA9ICJPQlNfVkFMVUVfU09DSUFMIiwgIk1FQVNVUkUiID0gIk1FQVNVUkVfU09DSUFMIikpDQoNCmxvbmVseV92MiA8LSByZW5hbWUobG9uZWx5X3YxLCByZXBsYWNlID0gYyhgUmVmZXJlbmNlIGFyZWFgID0gIlJlZmVyZW5jZV9hcmVhIiwgIk9CU19WQUxVRSIgPSAiT0JTX1ZBTFVFX0xPTkVMWSIsICJNZWFzdXJlIiA9ICJNZWFzdXJlX2xvbmVseSIsICJNRUFTVVJFIiA9ICJNRUFTVVJFX0xPTkVMWSIpKQ0KDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YyIDwtIHJlbmFtZShzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YxLCByZXBsYWNlID0gYyhgUmVmZXJlbmNlIGFyZWFgID0gIlJlZmVyZW5jZV9hcmVhIiwgIk9CU19WQUxVRSIgPSAiT0JTX1ZBTFVFX1NBVCIsICJNZWFzdXJlIiA9ICJNZWFzdXJlX3NhdCIsICJNRUFTVVJFIiA9ICJNRUFTVVJFX1NBVCIpKQ0KDQpgYGANCg0KYGBge3J9DQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YyWzE6MixdDQpgYGANCg0KDQpkcm9wIGNvbHVtbnMgbm90IGFudGljaXBhdGVkIHRvIGJlIG5lZWRlZCBvciBzdWJzZXQgb25seSB0aGUgY29sdW1ucyBJIHdpbGwgcmVxdWlyZQ0KDQoNCmBgYHtyfQ0KIyBDb2x1bW5zIHRvIGtlZXANCg0KcGhzX2NvbHVtbnNfdG9fa2VlcCA8LSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIsICJPQlNfVkFMVUVfUEhTIiwgIkhlYWx0aF9zdGF0dXMiLCAiSEVBTFRIX1NUQVRVUyIpDQplbF9jb2x1bW5zX3RvX2tlZXAgPC0gYygiUkVGX0FSRUEiLCAiUmVmZXJlbmNlX2FyZWEiLCAiVElNRV9QRVJJT0QiLCAiT0JTX1ZBTFVFX0VMIiwgIkVkdV9hdHRhaW5tZW50X2x2bCIsICJBVFRBSU5NRU5UX0xFViIpDQpzYWZldHlfY29sdW1uc190b19rZWVwIDwtIGMoIlJFRl9BUkVBIiwgIlJlZmVyZW5jZV9hcmVhIiwgIlRJTUVfUEVSSU9EIiwgIk9CU19WQUxVRV9TQUZFVFkiLCAiTWVhc3VyZV9zYWZldHkiLCAiTUVBU1VSRV9TQUZFVFkiKQ0Kc29jaWFsX2NvbHVtbnNfdG9fa2VlcCA8LSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIsICJPQlNfVkFMVUVfU09DSUFMIiwgIk1lYXN1cmVfc29jaWFsIiwgIk1FQVNVUkVfU09DSUFMIikNCmxvbmVseV9jb2x1bW5zX3RvX2tlZXAgPC0gYygiUkVGX0FSRUEiLCAiUmVmZXJlbmNlX2FyZWEiLCAiVElNRV9QRVJJT0QiLCAiT0JTX1ZBTFVFX0xPTkVMWSIsICJNZWFzdXJlX2xvbmVseSIsICJNRUFTVVJFX0xPTkVMWSIpDQpzYXRpc2ZhY3Rpb25fY29sdW1uc190b19rZWVwIDwtIGMoIlJFRl9BUkVBIiwgIlJlZmVyZW5jZV9hcmVhIiwgIlRJTUVfUEVSSU9EIiwgIk9CU19WQUxVRV9TQVQiLCAiTWVhc3VyZV9zYXQiLCAiTUVBU1VSRV9TQVQiKQ0KDQpwaHNfdjMgPC0gc3Vic2V0KHBoc192Miwgc2VsZWN0ID0gcGhzX2NvbHVtbnNfdG9fa2VlcCkNCmVsX3YzIDwtIHN1YnNldChlbF92Miwgc2VsZWN0ID0gZWxfY29sdW1uc190b19rZWVwKQ0Kc2FmZXR5X3YzIDwtIHN1YnNldChzYWZldHlfdjIsIHNlbGVjdCA9IHNhZmV0eV9jb2x1bW5zX3RvX2tlZXApDQpzb2NpYWxfc3VwcG9ydF9vcl9sYWNrX3YzIDwtIHN1YnNldChzb2NpYWxfc3VwcG9ydF9vcl9sYWNrX3YyLCBzZWxlY3QgPSBzb2NpYWxfY29sdW1uc190b19rZWVwKQ0KbG9uZWx5X3YzIDwtIHN1YnNldChsb25lbHlfdjIsIHNlbGVjdCA9IGxvbmVseV9jb2x1bW5zX3RvX2tlZXApDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YzIDwtIHN1YnNldChzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YyLCBzZWxlY3QgPSBzYXRpc2ZhY3Rpb25fY29sdW1uc190b19rZWVwKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0KcGhzX3YzDQoNCmVsX3YzDQoNCnNhZmV0eV92Mw0KDQpzb2NpYWxfc3VwcG9ydF9vcl9sYWNrX3YzDQoNCmxvbmVseV92Mw0KDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3YzDQoNCmBgYA0KDQpQaXZvdCBhbGwgZGF0YSBzZXRzIHByaW9yIHRvIG1lcmdpbmcgdGhlbS4NCg0KYGBge3J9DQoNCnBoc19waXZvdGVkIDwtIHBoc192MyAlPiUgDQogIHBpdm90X3dpZGVyKA0KICAgIGlkX2NvbHMgPSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIpLCANCiAgICBuYW1lc19mcm9tID0gYygiSEVBTFRIX1NUQVRVUyIpLA0KICAgIG5hbWVzX3ByZWZpeCA9ICJoZWFsdGhfc3RhdHVzXyIsDQogICAgdmFsdWVzX2Zyb20gPSAiT0JTX1ZBTFVFX1BIUyINCiAgICApDQoNCnBoc19waXZvdGVkDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQplbF9waXZvdGVkIDwtIGVsX3YzICU+JSANCiAgcGl2b3Rfd2lkZXIoDQogICAgaWRfY29scyA9IGMoIlJFRl9BUkVBIiwgIlJlZmVyZW5jZV9hcmVhIiwgIlRJTUVfUEVSSU9EIiksIA0KICAgIG5hbWVzX2Zyb20gPSBjKCJFZHVfYXR0YWlubWVudF9sdmwiKSwNCiAgICB2YWx1ZXNfZnJvbSA9ICJPQlNfVkFMVUVfRUwiDQogICAgKQ0KDQoNCmVsX3Bpdm90ZWQNCg0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KDQpzYWZldHlfcGl2b3RlZCA8LSBzYWZldHlfdjMgJT4lIA0KICBwaXZvdF93aWRlcigNCiAgICBpZF9jb2xzID0gYygiUkVGX0FSRUEiLCAiUmVmZXJlbmNlX2FyZWEiLCAiVElNRV9QRVJJT0QiKSwgDQogICAgbmFtZXNfZnJvbSA9IGMoIk1lYXN1cmVfc2FmZXR5IiksDQogICAgdmFsdWVzX2Zyb20gPSAiT0JTX1ZBTFVFX1NBRkVUWSINCiAgICApDQoNCg0Kc2FmZXR5X3Bpdm90ZWQNCg0KYGBgDQoNCmBgYHtyfQ0KDQpzb2NpYWxfc3VwcG9ydF9vcl9sYWNrX3Bpdm90ZWQgPC0gc29jaWFsX3N1cHBvcnRfb3JfbGFja192MyAlPiUgDQogIHBpdm90X3dpZGVyKA0KICAgIGlkX2NvbHMgPSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIpLCANCiAgICBuYW1lc19mcm9tID0gYygiTWVhc3VyZV9zb2NpYWwiKSwNCiAgICB2YWx1ZXNfZnJvbSA9ICJPQlNfVkFMVUVfU09DSUFMIg0KICAgICkNCg0Kc29jaWFsX3N1cHBvcnRfb3JfbGFja19waXZvdGVkDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpsb25lbHlfcGl2b3RlZCA8LSBsb25lbHlfdjMgJT4lIA0KICBwaXZvdF93aWRlcigNCiAgICBpZF9jb2xzID0gYygiUkVGX0FSRUEiLCAiUmVmZXJlbmNlX2FyZWEiLCAiVElNRV9QRVJJT0QiKSwgDQogICAgbmFtZXNfZnJvbSA9IGMoIk1lYXN1cmVfbG9uZWx5IiksDQogICAgdmFsdWVzX2Zyb20gPSAiT0JTX1ZBTFVFX0xPTkVMWSINCiAgICApDQoNCmxvbmVseV9waXZvdGVkDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpzYXRpc2ZhY3Rpb25fbGlmZV9yZWxzX3Bpdm90ZWQgPC0gc2F0aXNmYWN0aW9uX2xpZmVfcmVsc192MyAlPiUgDQogIHBpdm90X3dpZGVyKA0KICAgIGlkX2NvbHMgPSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIpLCANCiAgICBuYW1lc19mcm9tID0gYygiTWVhc3VyZV9zYXQiKSwNCiAgICB2YWx1ZXNfZnJvbSA9ICJPQlNfVkFMVUVfU0FUIg0KICAgICkNCg0Kc2F0aXNmYWN0aW9uX2xpZmVfcmVsc19waXZvdGVkDQoNCmBgYA0KDQoNCg0KTWVyZ2UgYWxsIDYgZGF0YSBzZXRzDQoNCg0KYGBge3J9DQoNCnBoc19lbCA8LSBtZXJnZSgNCiAgcGhzX3Bpdm90ZWQsDQogIGVsX3Bpdm90ZWQsDQogIGJ5ID0gYygiUkVGX0FSRUEiLCAiUmVmZXJlbmNlX2FyZWEiLCAiVElNRV9QRVJJT0QiKSwNCiAgYWxsID0gVFJVRQ0KKQ0KDQpwaHNfZWwNCg0KYGBgDQoNCmBgYHtyfQ0KDQpwaHNfZWxfc2FmZXR5IDwtIG1lcmdlKA0KICBwaHNfZWwsDQogIHNhZmV0eV9waXZvdGVkLA0KICBieSA9IGMoIlJFRl9BUkVBIiwgIlJlZmVyZW5jZV9hcmVhIiwgIlRJTUVfUEVSSU9EIiksDQogIGFsbCA9IFRSVUUNCikNCg0KcGhzX2VsX3NhZmV0eQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0KcGhzX2VsX3NhZmV0eV9zb2NpYWwgPC0gbWVyZ2UoDQogIHBoc19lbF9zYWZldHksDQogIHNvY2lhbF9zdXBwb3J0X29yX2xhY2tfcGl2b3RlZCwNCiAgYnkgPSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIpLA0KICBhbGwgPSBUUlVFDQopDQoNCnBoc19lbF9zYWZldHlfc29jaWFsDQoNCmBgYA0KDQpgYGB7cn0NCg0KcGhzX2VsX3NhZmV0eV9zb2NpYWxfbG9uZWx5IDwtIG1lcmdlKA0KICBwaHNfZWxfc2FmZXR5X3NvY2lhbCwNCiAgbG9uZWx5X3Bpdm90ZWQsDQogIGJ5ID0gYygiUkVGX0FSRUEiLCAiUmVmZXJlbmNlX2FyZWEiLCAiVElNRV9QRVJJT0QiKSwNCiAgYWxsID0gVFJVRQ0KKQ0KDQpwaHNfZWxfc2FmZXR5X3NvY2lhbF9sb25lbHkNCg0KYGBgDQoNCmBgYHtyfQ0KDQpwaHNfZWxfc2FmZXR5X3NvY2lhbF9sb25lbHlfc2F0aXNmYWN0aW9uIDwtIG1lcmdlKA0KICBwaHNfZWxfc2FmZXR5X3NvY2lhbF9sb25lbHksDQogIHNhdGlzZmFjdGlvbl9saWZlX3JlbHNfcGl2b3RlZCwNCiAgYnkgPSBjKCJSRUZfQVJFQSIsICJSZWZlcmVuY2VfYXJlYSIsICJUSU1FX1BFUklPRCIpLA0KICBhbGwgPSBUUlVFDQopDQoNCnBoc19lbF9zYWZldHlfc29jaWFsX2xvbmVseV9zYXRpc2ZhY3Rpb24NCg0KYGBgDQoNClVzZSBmaWxsIGZyb20gdGlkeXIgdG8gZmlsbCwgdXAgYW5kIGRvd24sIHRoZSBsb25lbHkgZGF0YQ0KDQpgYGB7cn0NCg0KcGhzX2VsX3NhZmV0eV9zb2NpYWxfbG9uZWx5X3NhdGlzZmFjdGlvbl9maWxsIDwtIHBoc19lbF9zYWZldHlfc29jaWFsX2xvbmVseV9zYXRpc2ZhY3Rpb24gfD4NCiAgZ3JvdXBfYnkoUmVmZXJlbmNlX2FyZWEpIHw+DQogIGZpbGwoYEZlZWxpbmcgbG9uZWx5YCwgLmRpcmVjdGlvbiA9ICJ1cGRvd24iKSB8Pg0KICB1bmdyb3VwKCkNCg0KcGhzX2VsX3NhZmV0eV9zb2NpYWxfbG9uZWx5X3NhdGlzZmFjdGlvbl9maWxsDQoNCmBgYA0KDQpgYGB7cn0NCg0KcGhzX2VsX3NhZmV0eV9zb2NpYWxfbG9uZWx5X3NhdGlzZmFjdGlvbl9maWxsZWQgPC0gcGhzX2VsX3NhZmV0eV9zb2NpYWxfbG9uZWx5X3NhdGlzZmFjdGlvbl9maWxsIHw+DQogIGdyb3VwX2J5KFJlZmVyZW5jZV9hcmVhKSB8Pg0KICBmaWxsKGBTYXRpc2ZhY3Rpb24gd2l0aCBwZXJzb25hbCByZWxhdGlvbnNoaXBzYCwgLmRpcmVjdGlvbiA9ICJ1cGRvd24iKSB8Pg0KICB1bmdyb3VwKCkNCg0KcGhzX2VsX3NhZmV0eV9zb2NpYWxfbG9uZWx5X3NhdGlzZmFjdGlvbl9maWxsZWQNCg0KYGBgDQoNCg0KYGBge3J9DQoNCmRmIDwtIHBoc19lbF9zYWZldHlfc29jaWFsX2xvbmVseV9zYXRpc2ZhY3Rpb25fZmlsbGVkIHw+DQogIGdyb3VwX2J5KFJlZmVyZW5jZV9hcmVhKSB8Pg0KICBmaWxsKGBMaWZlIHNhdGlzZmFjdGlvbmAsIC5kaXJlY3Rpb24gPSAidXBkb3duIikgfD4NCiAgdW5ncm91cCgpDQoNCmRmDQoNCmBgYA0KDQpGaW5hbCB2ZXJzaW9uIG9mIHRoZSBkYXRhc2V0IHRvIGJlIHVzZWQgaW4gdGhlIHNoaW55IGFwcC4NCg0KYGBge3J9DQoNCmRmICU+JSB2aWV3KCkNCmBgYA0KDQpgYGB7cn0NCiMgd3JpdGUuY3N2KGRmLCBmaWxlID0gIi4uL2RhdGEvZGYuY3N2IikNCmBgYA0KDQpgYGB7cn0NCmhpc3QoZGYkYEZlZWxpbmcgbG9uZWx5YCwgeGxhYj0ibG9uZWx5IikNCmBgYA0KYGBge3J9DQoNCnNvcnQodW5pcXVlKGRmJGBGZWVsaW5nIGxvbmVseWApKQ0KDQoNCmNsYXNzKGRmKQ0KYGBgDQoNCmBgYHtyfQ0KbWF4KGRmJGBGZWVsaW5nIGxvbmVseWAsIG5hLnJtID0gVFJVRSkNCmBgYA0KYGBge3J9DQpkZiAlPiUgdmlldygpDQoNCmBgYA0KDQo=